/*
 * Copyright (C) 2010 by Lei Shi (sjtushi@gmail.com)
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License, 
 * version 2, or any later versions.
 * --------------------
 * This xen_monitor daemon used as monitor engine.
 *
 * This service will do the works as listed: 
 *
 *   1. Load profile xml file from ioctl request of control app.
 *   2. Collect data from xen dmesg buffer.
 *   3. Process dmesg data and retrieve process file access info.
 *   4. Compare processed info with profile and log the alarm.
 *   5. Communicate with control app.
 *   6. Handle control app signal to update the monitored domid, 
 *      pid and reload profile.
 *
 */

#ifndef _XENMONITOR_H_
#define _XENMONITOR_H_

#include <unistd.h>
#include <signal.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <xenctrl.h>
#include <libxml/tree.h>
#include <libxml/parser.h>
#include "proc.h"

#ifdef DEBUG
#define DPRINTF(_f, _a...) printf ( _f, ## _a )
#else
#define DPRINTF(_f, _a...) ((void)0)
#endif

#define RUNMODE_RECORD_MODE     1
#define RUNMODE_MONITOR_MODE    2
#define MAX_FILENAME_LENGTH 	100
#define MAX_RULE_NUMBER 	100
#define BUFFER_SIZE             32768
#define DEFAULT_SLEEP_INTERVAL  2

//#define STATUS_SUCCESS          0
//#define STATUS_ERROR            -1
#define CMD_SET_DOMID           1
#define CMD_SET_PID             2
#define CMD_RELOAD_PROFILE      3
#define CMD_SET_RUNMODE         4
#define LOG_DIR                 "/var/log/monitor/"
#define LOG_FILE                "/var/log/monitor/service.log"
#define ALERT_FILE              "/var/log/monitor/alert.log"

/*
 * This daemon has two running mode: record mode and monitor mode.
 * Record mode will log all file access of the monitored process.
 * Monitor mode will monitor and log alert which doesn't match the
 * process access profile.
 *
 * Default we use monitor mode.
 */
unsigned int runmode = RUNMODE_MONITOR_MODE;

typedef enum {
   ACCESS_READONLY = 0,
   ACCESS_WRITEONLY = 1,
   ACCESS_READ_WRITE = 2,
} access_flag_t;

struct opened_file_info;

/*
 * TODO: This profile structure should be binary search tree mapped from 
 * XML profile structure. domid->pid->rule;
 *
 * Prototype Limit: In this prototype, we just use domid, pid pair, and 
 * this monitor service could only monitor one process with multi rules in 
 * one domain now.
 *
 */
typedef struct {
   char filename[MAX_FILENAME_LENGTH];
   access_flag_t type;
} monitor_rule_t;

typedef struct {
   int domid;
   int pid;
   monitor_rule_t rule_list[MAX_RULE_NUMBER];
   int rule_num;
} monitor_profile_t;

static monitor_profile_t profile = { 0 }; 

typedef struct opened_file_info{
   int domid;
   int pid;
   char filename[MAX_FILENAME_LENGTH];
   access_flag_t type;
   struct opened_file_info* next;
} opened_file_info_t;

/*
 * Init Daemon functions.
 */
int init_xen_monitor_daemon(void);

/*
 * Record mode function.
 */
#ifdef DEBUG
#define RECORD_PROFILE_FILE  "./record_profile"
#else
#define RECORD_PROFILE_FILE  "/etc/xen/monitor/record_profile"
#endif

void add_to_record_profile(int, int, const char *, int);

/*
 * Profile XML file handle functions.
 */
#ifdef DEBUG
#define PROFILE_FILE_NAME "./profile_example.xml"
#else
#define PROFILE_FILE_NAME "/etc/xen/monitor/profile.xml"
#endif
int load_profile(void);
int reload_profile(void);
int process_profile(void);

/*
 * Validate the access event with profile.
 * This function just compare the filename and access number with current
 * profile, if there is a filename and the right access number in the 
 * list, return ACCESS_ALLOWED. otherwise return ACCESS_INVALID. 
 * TODO: Will add more validation functions, not just the access number,
 * should include much more access details validation.
 */
#define ACCESS_ALLOWED    0
#define ACCESS_INVALID    1
int validate_access(int, int,const char*, int);

/*
 * Collecting and Process monitored process file access 
 * information.
 *
 * Collecting data from xen dmesg buffer or xen trace buffer.
 * In current prototype, we use the dmesg buffer which is much 
 * more flexsible than xen trace buffer which only handle uint 
 * structure less than 28*uint32 bytes.
 *
 * Processing data in char** dmesg only retrieves pid, and two 
 * parameters of open system call. This is the only info which 
 * could help us know the specfic process file access info.
 *
 */
int collect_data(char *,unsigned int);
int process_data(char *);

/*
 * Monitor loop process.
 * Collect and process data every 1 seconds by default, which could be
 * updated with char device ioctl. 
 */
int monitor_loop(int);

/*
 * helper functions
 */
int handle_ctrl_cmd(unsigned int, unsigned int);

#endif //_XENMONITOR_H_
